ES6 尚未問世前,在 JavaScript 中使用變數有很多細節要注意,例如使用與不使用 var 宣告變數的差異、全域變數和區域變數的作用範圍、hoisting 提升行為等等。ES6 的出現引入了 block scope 的觀念以及 const/let 兩種變數宣告方式,讓開發者寫出來的程式碼更容易維護,大大降低出錯的機會。讓我們來看看它們的強大吧!
首先我們先來瞭解什麼是 Block Scope。
基本上,只要是由一組大括號包起來的範圍就稱為 Block Scope(物件實字的大括號除外),常見的例如函式:
function() {
// Block Scope
}
if/else:
if () {
// Block Scope
} else if () {
// Block Scope
} else {
// Block Scope
}
switch/case:
switch () {
case: {
// Block Scope
}
default: {
// Block Scope
}
}
while 迴圈:
while () {
// Block Scope
}
for 迴圈:
for () {
// Block Scope
}
只要是經由 const 或 let 宣告的變數,它們的作用範圍就會被限制在 Block Scope,也就是說只有宣告變數所在的大括號中才能去存取變數的值,大括號之外則不行,例如:
function getAPlusB() {
const a = 1;
let b = 2;
return a + b;
}
console.log(a); // ReferenceError: a is not defined
console.log(b); // ReferenceError: b is not defined
上述例子在 getAPlusB 函式中,使用 const 宣告的變數 a,無法於函式之外取得它的值,若嘗試存取變數 a 會出現錯誤;使用 let 宣告的變數 b 也適用相同的規則。
接著我們來看看 const 和 let 兩種宣告變數的使用方式。
使用 const 宣告變數的方式與 var 相同,但不同的是 const 必須在宣告時同時賦值,而且在賦值之後就不能再修改其值,例如:
const name; // SyntaxError: Missing initializer in const declaration
const age = 18;
age = 19; // TypeError: Assignment to constant variable
若使用 const 宣告變數 name 但不賦值,會出現錯誤;而同樣使用 const 宣告變數 age,若嘗試重新賦值,也會出現錯誤。
使用 let 宣告變數的方式也與 var 相同,在宣告時不需同時賦值,即使賦值之後也可以再修改其值,例如:
let city;
city = 'Taipei';
let country = 'Taiwan';
country = 'China';
hoisting 是 JavaScript 語言的特性,它讓變數在宣告前就可以存取,例如:
console.log(language); // 不會出錯,但印出 undefined
var language = 'JavaScript';
但這樣的特性違背一般開發者習慣先宣告變數再使用變數的習慣,若改用 const 或 let:
console.log(fruit);
console.log(drink);
const fruit = 'orange'; // ReferenceError: Cannot access 'fruit' before initialization
let drink = 'coke'; // ReferenceError: Cannot access 'drink' before initialization
則在宣告變數之前就使用該變數時就會出現錯誤。
參考資料:
- JavaScript: Introduction to Scope (function scope, block scope) - https://dev.to/sandy8111112004/javascript-introduction-to-scope-function-scope-block-scope-d11